home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 8: LINUX Games / Linux Cubed Series 8 - LINUX Games.iso / games / x11 / rpg / crossfir.92 / crossfir / crossfire-0.92.5 / common / map.c < prev    next >
C/C++ Source or Header  |  1996-07-24  |  44KB  |  1,715 lines

  1. /*
  2.  * static char *rcsid_map_c =
  3.  *   "$Id: map.c,v 1.45 1996/06/10 06:20:13 master Exp $";
  4.  */
  5.  
  6. /*
  7.     CrossFire, A Multiplayer game for X-windows
  8.  
  9.     Copyright (C) 1992 Frank Tore Johansen
  10.  
  11.     This program is free software; you can redistribute it and/or modify
  12.     it under the terms of the GNU General Public License as published by
  13.     the Free Software Foundation; either version 2 of the License, or
  14.     (at your option) any later version.
  15.  
  16.     This program is distributed in the hope that it will be useful,
  17.     but WITHOUT ANY WARRANTY; without even the implied warranty of
  18.     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  19.     GNU General Public License for more details.
  20.  
  21.     You should have received a copy of the GNU General Public License
  22.     along with this program; if not, write to the Free Software
  23.     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  24.  
  25.     The author can be reached via e-mail to frankj@ifi.uio.no.
  26. */
  27.  
  28.  
  29. #include <global.h>
  30. #include <funcpoint.h>
  31. #if defined(UNIQUE_ITEMS) && defined (LOCK_ITEMS)
  32. #include <dirent.h>
  33. #endif
  34. #include <gods.h> 
  35.  
  36. extern int nrofallocobjects,nroffreeobjects;
  37.  
  38. #if defined (MACH) || defined (NeXT) || defined (__MACH__)
  39. #ifndef S_IWOTH
  40. #define S_IWOTH 0000200
  41. #endif
  42. #ifndef S_IWGRP
  43. #define S_IWGRP 0000020
  44. #endif
  45. #ifndef S_IWUSR
  46. #define S_IWUSR 0000002
  47. #endif
  48. #ifndef S_IROTH
  49. #define S_IROTH 0000400
  50. #endif
  51. #ifndef S_IRGRP
  52. #define S_IRGRP 0000040
  53. #endif
  54. #ifndef S_IRUSR
  55. #define S_IRUSR 0000004
  56. #endif
  57. #endif
  58. #if defined(MACH) || defined(vax) || defined(ibm032) || defined(NeXT) || defined(__MACH__)
  59. #ifndef S_ISDIR
  60. #define S_ISDIR(x) (((x) & S_IFMT) == S_IFDIR)
  61. #endif
  62. #ifndef S_ISREG
  63. #define S_ISREG(x) (((x) & S_IFMT) == S_IFREG)
  64. #endif
  65. #endif
  66.  
  67. /* This is a list of the suffix, uncompress and compress functions.  Thus,
  68.  * if you have some other compress program you want to use, the only thing
  69.  * that needs to be done is to extended this.
  70.  * The first entry must be NULL - this is what is used for non
  71.  * compressed files.
  72.  */
  73. char *uncomp[NROF_COMPRESS_METHODS][3] = {
  74.   {NULL, NULL, NULL},
  75. #ifdef COMPRESS_SUFFIX
  76.   {COMPRESS_SUFFIX, UNCOMPRESS, COMPRESS},
  77. #endif
  78.   {".Z", "uncompress", "compress"},
  79.   {".gz", "gunzip", "gzip"}
  80. };
  81.  
  82.  
  83. /*
  84.  * Returns the mapstruct which has a name matching the given argument.
  85.  */
  86.  
  87. mapstruct *has_been_loaded (char *name) {
  88.   mapstruct *map;
  89.  
  90.   if (!name || !*name) 
  91.     return 0;
  92.   for (map = first_map; map; map = map->next)
  93.       if (!strcmp (name, map->path))
  94.       break;
  95.   return (map);
  96. }
  97.  
  98. /*
  99.  * This makes a path absolute outside the world of Crossfire.
  100.  * In other words, it prepends LIBDIR/MAPDIR/ to the given path
  101.  * and returns the pointer to a static array containing the result.
  102.  */
  103.  
  104. char *create_pathname (char *name) {
  105.   static char buf[MAX_BUF];
  106.  
  107.   if (*name == '/')
  108.       sprintf (buf, "%s/%s%s", LibDir, MapDir, name);
  109.   else
  110.       sprintf (buf, "%s/%s/%s", LibDir, MapDir, name);
  111.   return (buf);
  112. }
  113.  
  114. #ifdef UNIQUE_ITEMS
  115. /*
  116.  * This makes absolute path to the itemfile where unique objects
  117.  * will be saved. Converts '/' to '@'. I think it's essier maintain
  118.  * files than full directory structure, but if this is problem it can 
  119.  * be changed.
  120.  */
  121. static char *create_items_path (char *s) {
  122.     static char buf[MAX_BUF];
  123.     char *t;
  124.     
  125.     if (*s == '/')
  126.       s++;
  127.  
  128.     sprintf (buf, "%s/%s/", LibDir, ItemsDir);
  129.  
  130.     for (t=buf+strlen(buf); *s; s++,t++)
  131.       if (*s == '/')
  132.           *t = '@';
  133.       else 
  134.           *t = *s;
  135.     *t = 0;
  136.     return (buf);  
  137. }
  138.  
  139. #ifdef LOCK_ITEMS
  140. /*
  141.  * Return 1 if lock is created, 0 if file is locked, -1 other error
  142.  */
  143. static int lock_unique_items(mapstruct *map, int v)
  144. {
  145.     char buf[MAX_BUF];
  146.     int fd;
  147.  
  148.     sprintf (buf, "%s.l%02d", create_items_path(map->path), v);
  149.     fd = open (buf, O_CREAT|O_EXCL, 0644);
  150.     if (fd < 0)
  151.       if (errno == EEXIST)
  152.           return 0;
  153.         else
  154.           return -1;
  155.     close (fd);
  156.     map->lock_items = v;
  157.     return 1;
  158. }
  159.  
  160. static void unlock_unique_items(mapstruct *m) {
  161.     char buf[MAX_BUF];
  162.  
  163.     if (m->lock_items) {
  164.       sprintf (buf, "%s.l%02d", create_items_path(m->path), m->lock_items);
  165.       m->lock_items = 0;
  166.       unlink(buf);
  167.     }
  168. }
  169.  
  170. void clean_lockfiles() {
  171.     mapstruct *m;
  172.  
  173.     LOG(llevDebug, "Cleaning unique items filelocks.\n");
  174.     for(m=first_map; m!=NULL; m=m->next)
  175.       if (m->lock_items)
  176.           unlock_unique_items(m);
  177. }
  178. #endif /* LOCK_ITEMS */
  179. #endif /* UNIQUE_ITEMS */
  180.  
  181.  
  182. /*
  183.  * This function checks if a file with the given path exists.
  184.  * -1 is returned if it failes, otherwise the mode of the file
  185.  * is returned.
  186.  * It tries out all the compression suffixes listed in the uncomp[] array.
  187.  */
  188.  
  189. int check_path (char *name)
  190. {
  191.     char buf[MAX_BUF], *endbuf;
  192.     struct stat statbuf;
  193.     int mode = 0, i;
  194.  
  195.     strcpy (buf, create_pathname(name));
  196.     if ((endbuf = strchr(buf, '\0')) == NULL)
  197.       return (-1);
  198.    
  199.     for (i = 0; i < NROF_COMPRESS_METHODS; i++) {
  200.       if (uncomp[i][0])
  201.         strcpy(endbuf, uncomp[i][0]);
  202.       else
  203.         *endbuf = '\0';
  204.       if (!stat (buf, &statbuf))
  205.         break;
  206.     }
  207.     if (i == NROF_COMPRESS_METHODS)
  208.       return (-1);
  209.     if (!S_ISREG (statbuf.st_mode))
  210.     return (0);
  211.  
  212.     if (((statbuf.st_mode & S_IRGRP) && getegid() == statbuf.st_gid) ||
  213.     ((statbuf.st_mode & S_IRUSR) && geteuid() == statbuf.st_uid) ||
  214.     (statbuf.st_mode & S_IROTH))
  215.     mode |= 4;
  216.  
  217.     if ((statbuf.st_mode & S_IWGRP && getegid() == statbuf.st_gid) ||
  218.     (statbuf.st_mode & S_IWUSR && geteuid() == statbuf.st_uid) ||
  219.     (statbuf.st_mode & S_IWOTH))
  220.     mode |= 2;
  221.     
  222.     return (mode);
  223. }
  224.  
  225. void dump_map_lights(mapstruct *m) {
  226.   objectlink *obl=m->light;
  227.   object *tmp=NULL;
  228.   while(obl) {
  229.      if((tmp=obl->ob)) 
  230.        LOG(llevDebug,"%s (%d) radius:%d\n",tmp->name,tmp->count,tmp->glow_radius); 
  231.      obl=obl->next;
  232.   } 
  233. }
  234.  
  235. /*
  236.  * Prints out debug-information about a map.
  237.  */
  238.  
  239. void dump_map(mapstruct *m) {
  240.   LOG(llevError,"Map %s status: %d.\n",m->path,m->in_memory);
  241.   LOG(llevError,"Size: %dx%d Start: %d,%d\n",
  242.           m->mapx,m->mapy,
  243.       EXIT_X(m->map_object), EXIT_Y(m->map_object));
  244.   if(m->map_object->msg!=NULL)
  245.     LOG(llevError,"Message:\n%s",m->map_object->msg);
  246.   if(m->tmpname!=NULL)
  247.     LOG(llevError,"Tmpname: %s\n",m->tmpname);
  248.   LOG(llevError,"Difficulty: %d\n",m->difficulty); 
  249. #ifdef USE_LIGHTING
  250.   LOG(llevError,"Darkness: %d\n",m->darkness); 
  251. #endif
  252. }
  253.  
  254. /*
  255.  * Prints out debug-information about all maps.
  256.  */
  257.  
  258. void dump_all_maps() {
  259.   mapstruct *m;
  260.   for(m=first_map;m!=NULL;m=m->next) {
  261.     LOG(llevError,"Map %s status %d.\n",m->path,m->in_memory);
  262.     LOG(llevError,"Tmpname: %s\n",m->tmpname);
  263.   }
  264. }
  265.  
  266. /*
  267.  * Returns true if a wall is present in a given location.
  268.  */
  269.  
  270. int wall(mapstruct *m, int x,int y) {
  271.  
  272.     if (out_of_map(m,x,y))
  273.         return 1;
  274.     return (get_map(m,x,y))->flags & P_NO_PASS;
  275. }
  276.  
  277. /*
  278.  * Returns true if it's impossible to see through the given coordinate
  279.  * in the given map.
  280.  */
  281.  
  282. int blocks_view(mapstruct *m, int x, int y) {
  283.   if(out_of_map(m,x,y))
  284.     return 1;
  285.   return (get_map(m,x,y))->flags & P_BLOCKSVIEW;
  286. }
  287.  
  288. /*
  289.  * Returns true if the given coordinate in the given map blocks magic.
  290.  */
  291.  
  292. int blocks_magic(mapstruct *m, int x, int y) {
  293.     if(out_of_map(m,x,y))
  294.     return 1;
  295.     return (get_map(m,x,y))->flags & P_NO_MAGIC;
  296.  
  297. }
  298.  
  299. /*
  300.  * Returns true if clerical spells cannot work here
  301.  */
  302. int blocks_cleric(mapstruct *m, int x, int y) {
  303.     if(out_of_map(m,x,y))
  304.     return 1;
  305.     return (get_map(m,x,y))->flags & P_NO_CLERIC;
  306. }
  307.  
  308. /*
  309.  * Returns true if the given coordinate in the given map blocks passage.
  310.  */
  311.  
  312. int blocked(mapstruct *m, int x, int y) {
  313.     int r;
  314.     MapLook *f;
  315.     if(out_of_map(m,x,y))
  316.     return 1;
  317.     f = get_map(m,x,y);
  318.     r = f->flags & (P_NO_PASS | P_IS_ALIVE);
  319.     return r;
  320. }
  321.  
  322. /*
  323.  * Returns true if the given coordinate in the map where the given object
  324.  * is, blocks the given object (which may be multi-part)
  325.  */
  326.  
  327. int blocked_link(object *ob, int x, int y) {
  328.   object *tmp;
  329.   if(out_of_map(ob->map,x,y))
  330.     return 1;
  331.   if (!blocked(ob->map,x,y)) /* no need to go further */
  332.       return 0; 
  333.   if(ob->head != NULL)
  334.     ob=ob->head;
  335.   for(tmp = get_map_ob(ob->map,x,y); tmp!= NULL; tmp = tmp->above)
  336.     if (QUERY_FLAG(tmp,FLAG_NO_PASS) || (QUERY_FLAG(tmp,FLAG_ALIVE) &&
  337.        tmp->head != ob && tmp != ob))
  338.           return 1;
  339.   return 0;
  340. }
  341.  
  342. /*
  343.  * Eneq(@csd.uu.se): This is a new version of blocked, this one handles objects
  344.  * that can be passed through by monsters with the CAN_PASS_THRU defined.
  345.  * Returns 1 if the object can not pass through that space.
  346.  */
  347.  
  348. int blocked_two(object *op, int x,int y) {
  349.   object *tmp;
  350.   if(out_of_map(op->map,x,y))
  351.     return 1;
  352.   tmp=get_map_ob(op->map,x,y);
  353.   for(tmp=get_map_ob(op->map,x,y);tmp!=NULL;tmp=tmp->above)
  354.     if((QUERY_FLAG(tmp,FLAG_ALIVE)&&tmp->type!=DOOR)||
  355.     (QUERY_FLAG(tmp,FLAG_NO_PASS)&&!QUERY_FLAG(tmp,FLAG_PASS_THRU))||
  356.         (QUERY_FLAG(tmp,FLAG_NO_PASS)&&QUERY_FLAG(tmp,FLAG_PASS_THRU)&&
  357.     !QUERY_FLAG(op,FLAG_CAN_PASS_THRU)))
  358.               return 1;
  359.   return 0;
  360. }
  361.  
  362. /*
  363.  * Returns true if the given archetype can't fit in the given spot.
  364.  */
  365.  
  366. int arch_blocked(archetype *at,mapstruct *m,int x,int y) {
  367.   archetype *tmp;
  368.   if(at==NULL)
  369.     return blocked(m,x,y);
  370.   for(tmp=at;tmp!=NULL;tmp=tmp->more)
  371.     if(blocked(m,x+tmp->clone.x,y+tmp->clone.y))
  372.       return 1;
  373.   return 0;
  374. }
  375.  
  376. /*
  377.  * Returns true if the given archetype can't fit into the map at the
  378.  * given spot (some part of it is outside the map-boundaries).
  379.  */
  380.  
  381. int arch_out_of_map(archetype *at,mapstruct *m,int x,int y) {
  382.   archetype *tmp;
  383.   if(at==NULL)
  384.     return out_of_map(m,x,y);
  385.   for(tmp=at;tmp!=NULL;tmp=tmp->more)
  386.     if(out_of_map(m,x+tmp->clone.x,y+tmp->clone.y))
  387.       return 1;
  388.   return 0;
  389. }
  390.  
  391. /*
  392.  * Goes through all objects in the given map, and does a sanity-check
  393.  * on all pointers.
  394.  */
  395.  
  396. void refresh_map(mapstruct *m) {
  397.   int x,y;
  398.   object *tmp,*tmp2=NULL,*active=NULL;
  399.  
  400.   if(m==NULL || m->in_memory != MAP_IN_MEMORY)
  401.     return;
  402.   for(x=0;x<m->mapx;x++)
  403.     for(y=0;y<m->mapy;y++) {
  404. /* Eneq(@csd.uu.se): Hunting down inappropriate objects in the map. The game
  405.    sometime hangs and tries to remove_removed objects etc. */
  406.       for(active=tmp=get_map_ob(m,x,y);tmp!=NULL;tmp=tmp2)
  407.       { /* how can we get objects with pointer<1024, mta */
  408.         if (tmp < (object *) 1024) /* map is uninitialized? */
  409.           break;
  410.         tmp2=tmp->above;
  411.         active=tmp;
  412.         if (QUERY_FLAG(tmp,FLAG_REMOVED)) {
  413.           LOG(llevError,"Crossfire: Found removed object in map.\n");
  414.           active=(tmp->above==NULL?tmp->below:tmp->above);
  415.           if (tmp->below==NULL&&tmp2==NULL)
  416.             m->map_ob[x+m->mapx*y]=NULL;
  417.           else if (tmp->below==NULL&&tmp2!=NULL) {
  418.             tmp2->below=NULL;
  419.             m->map_ob[x+m->mapx*y]=tmp2;
  420.           } else if (tmp->below!=NULL&&tmp2==NULL)
  421.             tmp->below->above=NULL;
  422.           else if (tmp->below!=NULL&&tmp2!=NULL) {
  423.             tmp->below->above=tmp2;
  424.             tmp2->below=tmp->below;
  425.           }
  426.           if (!QUERY_FLAG(tmp,FLAG_FREED))
  427.             free_object(tmp);
  428.         }
  429.         if (QUERY_FLAG(tmp,FLAG_FREED)&&!QUERY_FLAG(tmp,FLAG_REMOVED)) {
  430.           LOG(llevError, "Crossfire: Found freed object in map.\n");
  431.           remove_ob(tmp);
  432.         }
  433.       }
  434.  
  435.       if(active != NULL)
  436.         update_object(active);
  437.     }
  438. }
  439.  
  440. /*
  441.  * open_and_uncompress() first searches for the original filename.
  442.  * if it exist, then it opens it and returns the file-pointer.
  443.  * if not, it does two things depending on the flag.  If the flag
  444.  * is set, it tries to create the original file by uncompressing a .Z file.
  445.  * If the flag is not set, it creates a pipe that is used for
  446.  * reading the file (NOTE - you can not use fseek on pipes)
  447.  *
  448.  * The compressed pointer is set to nonzero if the file is
  449.  * compressed (and thus,  fp is actually a pipe.)  It returns 0
  450.  * if it is a normal file
  451.  *
  452.  * (Note, the COMPRESS_SUFFIX is used instead of ".Z", thus it can easily
  453.  * be changed in the config file.)
  454.  */
  455.  
  456. FILE *open_and_uncompress(char *name,int flag, int *compressed) {
  457.   FILE *fp;
  458.   char buf[MAX_BUF],buf2[MAX_BUF], *bufend;
  459.   int try_once = 0;
  460.  
  461.   strcpy(buf, name);
  462.   bufend = buf + strlen(buf);
  463.  
  464. /*  LOG(llevDebug, "open_and_uncompress(%s)\n", name);
  465. */
  466.  
  467.   /* strip off any compression prefixes that may exist */
  468.   for (*compressed = 0; *compressed < NROF_COMPRESS_METHODS; (*compressed)++) {
  469.     if ((uncomp[*compressed][0]) &&
  470.       (!strcmp(uncomp[*compressed][0], bufend - strlen(uncomp[*compressed][0])))) {
  471.     buf[strlen(buf) - strlen(uncomp[*compressed][0])] = '\0';
  472.     bufend = buf + strlen(buf);
  473.     }
  474.   }
  475.   for (*compressed = 0; *compressed < NROF_COMPRESS_METHODS; (*compressed)++) {
  476.     struct stat statbuf;
  477.  
  478.     if (uncomp[*compressed][0])
  479.         strcpy(bufend, uncomp[*compressed][0]);
  480.     if (stat(buf, &statbuf)) {
  481.  
  482. /*      LOG(llevDebug, "Failed to stat %s\n", buf);
  483. */
  484.       continue;
  485.     }
  486. /*    LOG(llevDebug, "Found file %s\n", buf);
  487. */
  488.     if (uncomp[*compressed][0]) {
  489.       strcpy(buf2, uncomp[*compressed][1]);
  490.       strcat(buf2, " < ");
  491.       strcat(buf2, buf);
  492.       if (flag) {
  493.         int i;
  494.         if (try_once) {
  495.           LOG(llevError, "Failed to open %s after decompression.\n", name);
  496.           return NULL;
  497.         }
  498.         try_once = 1;
  499.         strcat(buf2, " > ");
  500.         strcat(buf2, name);
  501.         LOG(llevDebug, "system(%s)\n", buf2);
  502.         if ((i=system(buf2))) {
  503.           LOG(llevError, "system(%s) returned %d\n", buf2, i);
  504.           return NULL;
  505.         }
  506.         unlink(buf);        /* Delete the original */
  507.         *compressed = '\0';    /* Restart the loop from the beginning */
  508.         chmod(name, statbuf.st_mode);
  509.         continue;
  510.       }
  511.       if ((fp = popen(buf2, "r")) != NULL)
  512.         return fp;
  513.     } else if((fp=fopen(name,"r"))!=NULL)
  514.       return fp;
  515.   }
  516.   LOG(llevDebug, "Can't open %s\n", name);
  517.   return NULL;
  518. }
  519.  
  520. /*
  521.  * See open_and_uncompress().
  522.  */
  523.  
  524. void close_and_delete(FILE *fp, int compressed) {
  525.   if (compressed)
  526.     pclose(fp);
  527.   else
  528.     fclose(fp);
  529. }
  530.  
  531. /* When the map is loaded, load_object does not actually insert objects
  532.  * into inventory, but just links them.  What this does is go through
  533.  * and insert them properly.
  534.  * The object 'container' is the object that contains the inventory.
  535.  * This is needed so that we can update the containers weight.
  536.  */
  537.  
  538.  
  539. void fix_container(object *container)
  540. {
  541.     object *tmp=container->inv, *next;
  542.  
  543.     container->inv=NULL;
  544.     while (tmp!=NULL) {
  545.     next = tmp->below;
  546.     if (tmp->inv)
  547.         fix_container(tmp);
  548.     (void) insert_ob_in_ob(tmp,container);
  549.     tmp = next;
  550.     }
  551.     /* sum_weight will go through and calculate what all the containers are
  552.      * carrying.
  553.      */
  554.     sum_weight(container);
  555. }
  556.  
  557. /*
  558.  * Loads (ands parses) the objects into a given map from the specified
  559.  * file pointer.
  560.  * If block is true, the game will be blocked until all objects have
  561.  * been loaded (this is needed to avoid certain critical regions).
  562.  */
  563.  
  564. void load_objects (mapstruct *m, FILE *fp, int block) {
  565.     int i;
  566. #if defined(PROCESS_WHILE_LOADING) && CHECK_ACTIVE_MAPS
  567.     int  j = 0;
  568. #endif
  569.  
  570.     object *op, *prev=NULL,*last_more=NULL;
  571.     MapLook    maplook;
  572.  
  573.     op=get_object();
  574.     op->map = m; /* To handle buttons correctly */
  575.  
  576.     while((i=load_object(fp,op))) {
  577.     /* if the archetype for the object is null, means that we
  578.      * got an invalid object.  Don't do anythign with it - the game
  579.      * or editor will not be able to do anything with it either.
  580.      */
  581.     if (op->arch==NULL) {
  582.         if (op->name!=NULL)
  583.         LOG(llevDebug,"Discarded object %s - invalid archetype.\n",op->name);
  584.         continue;
  585.     }
  586.     /* this hack allows for 'unused' altars (see below) to have a 
  587.       * random god (see the 'god table' in god.c) associated w/ it -b.t. 
  588.      */
  589. #ifdef MULTIPLE_GODS
  590.     if(op->type==ALTAR && !op->value && !editor && !op->stats.sp)
  591.        if(baptize_altar(op))
  592.         LOG(llevDebug,"Baptized altar to %s\n",op->title);
  593. #endif
  594.     switch(i) {
  595.       case 1:
  596.         insert_ob_in_map(op,m);
  597.         if (op->inv) fix_container(op);
  598.         prev=op,last_more=op;
  599.         break;
  600.  
  601.       case 2:
  602.         op = insert_ob_in_ob(op,prev);
  603.         break;
  604.  
  605.       case 3:
  606.         insert_ob_in_map(op,m);
  607.         op->head=prev,last_more->more=op,last_more=op;
  608.         break;
  609.     }
  610.  
  611.     /* Small hack to set the floor object for the maps.  This
  612.      * increases the performance for color pixmaps, as not the floor
  613.      * and top object are easily accessible.  Before, it had to
  614.      * search through the objects for the map space to find the
  615.      * floor.
  616.      *
  617.      * This should probably be someplace else, but I could not
  618.      * figure out the set_map_ob function, which then calls the
  619.      * set_map function, in where the floor is determined.
  620.      * I am also assuming that the floor can not change.  As such,
  621.      * the floor only needs to be determined once.
  622.      * Mark Wedel (master@rahul.net)
  623.      */
  624.     if (QUERY_FLAG(op,FLAG_IS_FLOOR)) {
  625.         maplook.face = op->face;
  626.         maplook.flags = 0;
  627.         m->floor[op->x+ m->mapx*op->y] = maplook;
  628.     }
  629.     op=get_object();
  630.         op->map = m;
  631. #if defined(PROCESS_WHILE_LOADING) && CHECK_ACTIVE_MAPS
  632.     if(!block && j++>CHECK_ACTIVE_MAPS) {
  633.         j=0;
  634.         /* We don't want to freeze the whole game too long */
  635.         (*process_active_maps_func)(); 
  636.     }
  637. #endif
  638.     }
  639.     free_object(op);
  640. }
  641.  
  642. void save_objects (mapstruct *m, FILE *fp, FILE *fp2) {
  643.     int i, j = 0;
  644.     object *op, *tmp, *otmp;
  645. #if 0 /*defined(PROCESS_WHILE_LOADING) && CHECK_ACTIVE_MAPS*/
  646.     int  elapsed = 0;
  647. #endif
  648.     /* first pass - save one-part objects */
  649.     for(i = 0; i < m->mapx; i++)
  650.     for (j = 0; j < m->mapy; j++)
  651.         for(op = get_map_ob (m, i, j); op; op = otmp) {
  652.         otmp = op->above;
  653.  
  654.         if(op->type == PLAYER) {
  655.             LOG(llevDebug, "Player on map that is being saved\n");
  656.             continue;
  657.         }
  658.  
  659.         if (op->head || op->more || op->owner)
  660.             continue;
  661.  
  662.               save_object(QUERY_FLAG(op, FLAG_UNIQUE) ? fp2 : fp, op, 3);
  663.         /* don't check and don't remove */
  664.  
  665. /* Would be nice to let players still do stuff while a map is saving.
  666.  * The problem is, having a player enter a map that is in the process
  667.  * of being saved.  The maps needs to finish saving, and then be
  668.  * re-loaded.
  669.  */
  670. #if 0 /*defined(PROCESS_WHILE_LOADING) && CHECK_ACTIVE_MAPS*/
  671.           if(elapsed++>CHECK_ACTIVE_MAPS) {
  672.         elapsed=0;
  673.         /* We don't want to freeze the whole game too long */
  674.         (*process_active_maps_func)(); 
  675.           }
  676. #endif
  677.         }
  678.     /* second pass - save multi-part objects */
  679.     for(i = 0; i < m->mapx; i++)
  680.         for (j = 0; j < m->mapy; j++)
  681.             for(op = get_map_ob (m, i, j); op; op = otmp) {
  682.                 otmp = op->above;
  683.  
  684.         if(op->type == PLAYER) {
  685.             LOG(llevDebug, "Player on map that is being saved\n");
  686.             continue;
  687.         }
  688.  
  689.         if (op->head || !op->more || op->owner)
  690.             continue;
  691.  
  692.               save_object(QUERY_FLAG(op, FLAG_UNIQUE) ? fp2 : fp, op, 3);
  693.                 /* don't check and don't remove */
  694.  
  695.         for (tmp = op->more; tmp; tmp = tmp->more) {
  696.                   fprintf (QUERY_FLAG(tmp, FLAG_UNIQUE) ? fp2:fp, "More\n");
  697.                   save_object(QUERY_FLAG(tmp, FLAG_UNIQUE) ? fp2:fp, tmp, 3);
  698.             /* don't check and don't remove */
  699.         }
  700. #if 0 /*defined(PROCESS_WHILE_LOADING) && CHECK_ACTIVE_MAPS*/
  701.           if(elapsed++>CHECK_ACTIVE_MAPS) {
  702.         elapsed=0;
  703.         /* We don't want to freeze the whole game too long */
  704.         (*process_active_maps_func)(); 
  705.           }
  706. #endif
  707.         }
  708. }
  709.  
  710. /*
  711.  * Opens the file "filename" and reads information about the map
  712.  * from the given file, and stores it in a newly allocated
  713.  * mapstruct.  A pointer to this structure is returned, or NULL on failure.
  714.  * If block is true, it will block the game while reading the objects.
  715.  */
  716.  
  717. mapstruct *load_original_map(char *filename, int block) {
  718.     FILE *fp;
  719.     mapstruct *m;
  720.     object *op;
  721.     int comp;
  722.     
  723.     LOG(llevDebug, "load_original_map: %s\n", filename);
  724.     if((fp=open_and_uncompress(create_pathname(filename), 0, &comp))==NULL) {
  725.       LOG(llevError,"Can't open %s\n", create_pathname(filename));
  726.     perror("Can't read map file");
  727.     return (NULL);
  728.     }
  729.         
  730.     op = get_object();
  731.  
  732.     if (!load_object(fp, op) || op->type != MAP) {
  733.     LOG(llevError,"Error in map (%s) - map object not found\n", filename);
  734.         close_and_delete(fp, comp);
  735.     return (NULL);
  736.     }
  737.     if (op->arch == NULL) {
  738.       LOG(llevDebug, "Mapobject had no archetype\n");
  739.       op->arch = find_archetype("map");
  740.       if (op->arch == NULL)
  741.         LOG(llevError, "Archetype map lacks.");
  742.       if (op->arch->clone.type != MAP)
  743.         LOG(llevDebug, "Archetype map has wrong type.");
  744.     }
  745.     m = get_empty_map (op->x, op->y);
  746.  
  747.     strcpy (m->path, filename);
  748.     m->compressed = comp;
  749.  
  750.     if (m->map_object)
  751.     free_object (m->map_object);
  752.     m->map_object = op;
  753.     op->map = m;
  754.  
  755.     m->in_memory=MAP_LOADING;
  756.     load_objects (m, fp, block);
  757.     close_and_delete(fp, comp);
  758.     m->in_memory=MAP_IN_MEMORY;
  759.     m->difficulty=calculate_difficulty(m);
  760.     m->darkness=m->map_object->invisible;
  761.     m->do_los=0;
  762.     set_map_reset_time(m);
  763.  
  764.     return (m);
  765. }
  766.  
  767. /*
  768.  * Loads a map, which has been loaded earlier, from file.
  769.  */
  770.  
  771. void load_temporary_map(mapstruct *m) {
  772.     FILE *fp;
  773.     object *op;
  774.     int comp;
  775.     
  776.     if (!m->tmpname) {
  777.     LOG(llevError, "No temporary filename for map %s\n", m->path);
  778.         m = load_original_map(m->path,0);
  779.     return;
  780.     }
  781.  
  782.     if((fp=open_and_uncompress(m->tmpname,0, &comp))==NULL) {
  783.     LOG(llevError,"Can't open %s\n",m->tmpname);
  784.     perror("Can't read map file");
  785.         m = load_original_map(m->path,0);
  786.     return;
  787.     }
  788.     
  789.     op = get_object();
  790.  
  791.     load_object(fp,op);
  792.     if (op->arch == NULL || op->type != MAP) {
  793.     LOG(llevError,"Error in temporary map '%s'\n", m->path);
  794.         m = load_original_map(m->path,0);
  795.     return;
  796.     }
  797.  
  798.     m->compressed = comp;
  799.  
  800.  
  801.     if (m->map_object)
  802.     free_object (m->map_object);
  803.     m->map_object = op;
  804.  
  805.     allocate_map(m);
  806.     clear_map(m);
  807.  
  808.     m->in_memory=MAP_LOADING;
  809.     load_objects (m, fp, 0);
  810.     close_and_delete(fp, comp);
  811.     m->in_memory=MAP_IN_MEMORY;
  812. }
  813.  
  814. #ifdef UNIQUE_ITEMS
  815. void merge_files (char *s1, char *s2)
  816. {
  817.     char buf[MAX_BUF];
  818.     FILE *fp1, *fp2;
  819.     int i;
  820.  
  821.     if ((fp1 = fopen (s1, "a+")) == NULL) {
  822.       LOG(llevError, "Can't open file for append '%s'\n", s1);
  823.       return;
  824.     }
  825.     if ((fp2 = fopen (s2, "r")) == NULL) {
  826.       LOG(llevError, "Can't open file for reading '%s'\n", s2);
  827.       fclose (fp1);
  828.       return;
  829.     }
  830.     while ((i = fread(buf, 1, MAX_BUF, fp2)) > 0)
  831.       fwrite (buf, 1, i, fp1);
  832.     fclose (fp1);
  833.     fclose (fp2);
  834. }
  835.  
  836. /*
  837.  * returns version number if s1 is filename which is for map s2
  838.  */
  839. int match_filename(char *s1, char *s2)
  840. {
  841.     int n;
  842.  
  843.     if (*s2 == '/')
  844.       s2++;
  845.     
  846.     while (*s2) {
  847.       if (*s1 != *s2 && *s2 != '/' && *s1 != '@')
  848.           return 0;
  849.       s1++, s2++;
  850.     }
  851.     return sscanf(s1, ".v%d", &n) == 1 ? n : 0;
  852. }
  853.  
  854. void delete_unique_items(mapstruct *m)
  855. {
  856.     int i,j;
  857.     object *op, *next;
  858.  
  859.     for(i=0; i<m->map_object->x; i++)
  860.       for(j=0; j<m->map_object->y; j++)
  861.           for (op=get_map_ob(m, i, j); op; op=next) {
  862.               next = op->above;
  863.               if(op->head == NULL && QUERY_FLAG(op, FLAG_UNIQUE)) {
  864.                   clean_object(op);
  865.                   remove_ob(op);
  866.                   free_object(op);
  867.               }
  868.           }
  869. }
  870.  
  871. /*
  872.  * Loads unique objects from file(s) into the map which is in memory
  873.  */
  874. void load_unique_objects(mapstruct *m) {
  875.     FILE *fp;
  876.     int comp;
  877.     char firstname[MAX_BUF];
  878.  
  879. #ifdef LOCK_ITEMS
  880.     int v, firstlock = 0;
  881.     DIR *dirptr;
  882.     struct xdirect *dp;
  883.  
  884.     if ((dirptr = opendir(create_items_path(""))) == NULL) {
  885.       LOG(llevDebug,"Can't open dir %s\n", create_items_path(""));
  886.       return;
  887.     }
  888.     while ((dp = xreaddir(dirptr,0)) != NULL ) {
  889.       if ((v = match_filename(dp->d_name,  m->path))) {
  890.           if (lock_unique_items(m, v) != 1) {
  891.               LOG(llevDebug,"Unique items are already locked.\n");
  892.               continue;
  893.           }
  894.           if (firstlock == 0) {
  895.               strcpy (firstname, create_items_path(dp->d_name));
  896.               firstlock = v;
  897.           } else {
  898.               merge_files (firstname, create_items_path(dp->d_name));
  899.               unlink (create_items_path(dp->d_name));
  900.               unlock_unique_items(m);     /* clears lock_items, so */
  901.               m->lock_items = firstlock; /* put original lock back */
  902.           }
  903.       }
  904.     }   
  905.     closedir(dirptr);
  906.     if (firstlock == 0)
  907.       return;
  908. #else 
  909.     strcpy (firstname, create_items_path(m->path));
  910.     strcat (firstname, ".v00");
  911.  
  912. #endif /* LOCK_ITEMS */
  913.  
  914.     if(! (fp=open_and_uncompress(firstname, 0, &comp))) {
  915.       LOG(llevDebug, "Can't open unique items file %s\n", firstname);
  916.       return;
  917.     }
  918.     m->in_memory=MAP_LOADING;
  919.     if (m->tmpname == NULL)    /* if we have loaded unique items from */
  920.       delete_unique_items(m); /* original map before, don't duplicate them */
  921.     load_objects (m, fp, 0);
  922.     close_and_delete(fp, comp);
  923.     m->in_memory=MAP_IN_MEMORY;
  924. }
  925. #endif
  926.  
  927. #define MAXQUEUE 10000
  928. static object* ob_queue[MAXQUEUE];
  929. static int ob_queue_start=0;
  930. static int ob_queue_end=0;
  931.     
  932. void queue_push(object* m_ob){
  933.     ob_queue[ob_queue_end++]=m_ob;
  934.     if(ob_queue_end==MAXQUEUE)
  935.       ob_queue_end=0;
  936. }
  937.     
  938. object *queue_pop(void){
  939.     object* m_ob;
  940.     if(ob_queue_start==ob_queue_end)
  941.       return(NULL);
  942.     m_ob=ob_queue[ob_queue_start++];
  943.     if(ob_queue_start==MAXQUEUE)
  944.       ob_queue_start=0;
  945.     return(m_ob);
  946. }
  947.  
  948. /*
  949.  * Saves a map to file.  If flag is set, it is saved into the same
  950.  * file it was (originally) loaded from.  Otherwise a temporary
  951.  * filename will be genarated, and the file will be stored there.
  952.  * The temporary filename will be stored in the mapstructure.
  953.  */
  954.  
  955. int new_save_map(mapstruct *m, int flag) {
  956.     FILE *fp;
  957.     char filename[MAX_BUF];
  958. #ifdef UNIQUE_ITEMS
  959.     FILE *fp2;
  960.     char buf[MAX_BUF];
  961. #endif
  962.     
  963.     if (flag && !*m->path) {
  964.     LOG(llevError,"Tried to save map without path.\n");
  965.     return -1;
  966.     }
  967.     
  968.     if(flag) {
  969.     strcpy (filename, create_pathname (m->path));
  970.     /* If the compression suffix already exists on the filename, don't
  971.      * put it on again.  This nasty looking strcmp checks to see if the
  972.      * compression suffix is at the end of the filename already.
  973.      */
  974.         if (m->compressed &&
  975.       strcmp((filename + strlen(filename)-strlen(uncomp[m->compressed][0])),
  976.          uncomp[m->compressed][0]))
  977.               strcat(filename, uncomp[m->compressed][0]);
  978.     make_path_to_file (filename);
  979.     } else {
  980.     if (!m->tmpname)
  981.         m->tmpname = tempnam(TMPDIR,NULL);
  982.     strcpy(filename, m->tmpname);
  983.     }
  984.     LOG(llevDebug,"Saving map %s\n",m->path);
  985.     m->in_memory = MAP_SAVING;
  986.     if (m->compressed && flag) { /* Compress if it isn't a temporary save */
  987.       char buf[MAX_BUF];
  988.       strcpy(buf, uncomp[m->compressed][2]);
  989.       strcat(buf, " > ");
  990.       strcat(buf, filename);
  991.       fp = popen(buf, "w");
  992.     } else
  993.       fp = fopen(filename, "w");
  994.     if(fp == NULL) {
  995.       perror("Can't open file for saving");
  996.       return -1;
  997.     }
  998.     
  999.     if (!m->map_object) {
  1000.     LOG(llevError, "no map object for map %s!\n", m->path);
  1001.     return -1;
  1002.     }
  1003.  
  1004.     save_object (fp, m->map_object, 3);
  1005.  
  1006. #ifdef UNIQUE_ITEMS
  1007.     /* In the game save unique items in the different file, but
  1008.      * in the editor save them to the normal map file.
  1009.      */
  1010.     fp2 = fp; /* save unique items into fp2 */
  1011.     if (flag == 0) {
  1012.       int lock = 0;
  1013. #ifdef LOCK_ITEMS
  1014.       lock = m->lock_items;
  1015.       if (lock == 0) {
  1016.           do {
  1017.               lock++;
  1018.           } while (lock < 10 && lock_unique_items(m, lock) != 1);
  1019.           if (lock >= 10) {
  1020.               LOG(llevError, "Over 10 item locks in map %s!\n", m->path);
  1021.           }
  1022.       }
  1023. #endif
  1024.       strcpy (buf, create_items_path (m->path));
  1025.       sprintf (buf + strlen(buf), ".v%02d", lock);
  1026.       if ((fp2 = fopen (buf, "w")) == NULL) {
  1027.           LOG(llevError, "Can't open items file %s\n", buf);
  1028.       }
  1029.       save_objects (m, fp, fp2);
  1030.       if (fp2 != NULL) {
  1031.       if (ftell (fp2) == 0) {
  1032.         /* remove the file if it's empty */
  1033.         fclose (fp2);
  1034.         unlink (buf);
  1035.       } else {
  1036.         fclose (fp2);
  1037.         chmod (buf, SAVE_MODE);
  1038.       }
  1039.       }
  1040. #ifdef LOCK_ITEMS
  1041.       unlock_unique_items(m);
  1042. #endif
  1043.     } else { /* save same file when not playing, like in editor */
  1044.       save_objects (m, fp, fp);
  1045.     }
  1046. #else
  1047.     save_objects (m, fp, fp);
  1048. #endif /* UNIQUE_ITEMS */
  1049.  
  1050.     if (m->compressed && !flag)
  1051.       pclose(fp);
  1052.     else
  1053.       fclose(fp);
  1054.  
  1055. #if 0
  1056.     if (flag && m->read_only) /* Huh ! */
  1057.     chmod (filename, 0644);
  1058.     else
  1059. #endif
  1060.     chmod (filename, 0644);
  1061.     return 0;
  1062. }
  1063. /*
  1064.  * If any directories in the given path doesn't exist, they are created.
  1065.  */
  1066.  
  1067. void make_path_to_file (char *filename)
  1068. {
  1069.     char buf[MAX_BUF], *cp = buf;
  1070.     struct stat statbuf;
  1071.  
  1072.     if (!filename || !*filename)
  1073.     return;
  1074.     strcpy (buf, filename);
  1075.     LOG(llevDebug, "make_path_tofile %s...", filename);
  1076.     while ((cp = strchr (cp + 1, (int) '/'))) {
  1077.     *cp = '\0';
  1078.     LOG(llevDebug, "Checking %s...", buf);
  1079.     if (stat (buf, &statbuf) || !S_ISDIR (statbuf.st_mode)) {
  1080.         LOG(llevDebug, "Was not dir...");
  1081.         if (mkdir (buf, 0777)) {
  1082.         perror ("Couldn't make path to file");
  1083.         return;
  1084.         }
  1085.         LOG(llevDebug, "Made dir.\n");
  1086.     } else
  1087.         LOG(llevDebug, "Was dir\n");
  1088.     *cp = '/';
  1089.     }
  1090. }
  1091.  
  1092.  
  1093. /*
  1094.  * Clears the arrays containing object-pointers and outlook of a map.
  1095.  */
  1096.  
  1097. void clear_map(mapstruct *m) {
  1098.     MapLook *aptr, *endptr;
  1099.  
  1100.     endptr=m->map+m->mapx*m->mapy;
  1101.     for(aptr=m->map; aptr < endptr; ++aptr)
  1102.     *aptr = blank_look;
  1103.     endptr=m->floor+m->mapx*m->mapy;
  1104.     for(aptr=m->floor; aptr < endptr; ++aptr)
  1105.     *aptr = blank_look;
  1106. #ifdef DOUBLE_FLOOR
  1107.     endptr=m->floor2+m->mapx*m->mapy;
  1108.     for(aptr=m->floor2; aptr < endptr; ++aptr)
  1109.     *aptr = blank_look;
  1110. #endif
  1111.     memset(m->map_ob, 0,sizeof(object *)*m->mapx*m->mapy);
  1112. }
  1113.  
  1114. /*
  1115.  * This function relinks all _pointers_ to the objects from
  1116.  * one map to another.
  1117.  * Note: You can _not_ free the objects in the original map
  1118.  * after this function has been called.
  1119.  * (What happened to this function? It no longer copies the pointers! -Frank)
  1120.  */
  1121.  
  1122. void copy_map(mapstruct *m1, mapstruct *m2) {
  1123.   int x,y;
  1124.  
  1125.   strncpy(m2->path,m1->path,BIG_NAME);
  1126.   x = m2->mapx;
  1127.   y = m2->mapy;
  1128.   copy_object (m1->map_object, m2->map_object);
  1129.   m2->mapx = x;
  1130.   m2->mapy = y;  
  1131.  
  1132.   for(x=0;x<m1->mapx&&x<m2->mapx;x++)
  1133.     for(y=0;y<m1->mapy&&y<m2->mapy;y++) {
  1134.       set_map(m2,x,y,get_map(m1,x,y));
  1135.     }
  1136. }
  1137.  
  1138. /*
  1139.  * This function, like copy_map(), relinks all _pointers_ from
  1140.  * one map to the other map.
  1141.  */
  1142.  
  1143. void relink_objs_offset(mapstruct *m1, mapstruct *m2, int dx, int dy) {
  1144.   int x,y;
  1145.   object *ob;
  1146.  
  1147.   for (x = 0; x < m1->mapx && x < m2->mapx + dx; x++)
  1148.     for (y = 0; y < m1->mapy && y < m2->mapy + dy; y++) {
  1149.       set_map(m2, x + dx, y + dy, get_map(m1, x, y));
  1150.       set_map_ob(m2, x + dx, y + dy, get_map_ob(m1, x, y));
  1151.       set_map_ob(m1, x, y, (object *) NULL);
  1152.       for (ob = get_map_ob(m2, x + dx, y + dy); ob; ob = ob->above)
  1153.       {
  1154.         ob->x = x + dx;
  1155.         ob->y = y + dy;
  1156.         ob->map = m2;
  1157.       }
  1158.     }
  1159. }
  1160.  
  1161. /*
  1162.  * Remove and free all objects in the inventory of the given object.
  1163.  * object.c ?
  1164.  */
  1165.  
  1166. void clean_object(object *op)
  1167. {
  1168.   object *tmp, *next;
  1169.  
  1170.   for(tmp = op->inv; tmp; tmp = next)
  1171.   {
  1172.     next = tmp->below;
  1173.     clean_object(tmp);
  1174.     remove_ob(tmp);
  1175.     free_object(tmp);
  1176.   }
  1177. }
  1178.  
  1179. #if 0 /* Why make it so difficult?  I believe the below is buggy */
  1180.  
  1181. void clean_object(object *op) {
  1182.   object *tmp;
  1183.   while((tmp=op->inv)!=NULL) {
  1184.     clean_object(tmp);
  1185.  
  1186. /* Eneq(@csd.uu.se): We'll have to move up the inventory or else op->inv
  1187.    always will point to the same object. */
  1188.     
  1189.     if (tmp->below!=NULL)
  1190.       tmp->below->above=NULL;
  1191.     op->inv=tmp->below;
  1192.     tmp->below=NULL;
  1193.  
  1194.     remove_ob(tmp);
  1195.     free_object(tmp);
  1196.   }
  1197. }
  1198.  
  1199. #endif
  1200.  
  1201. /*
  1202.  * Remove and free all objects in the given map.
  1203.  */
  1204.  
  1205. void free_all_objects(mapstruct *m) {
  1206.   int i,j;
  1207.   object *op;
  1208.  
  1209.   for(i=0;i<m->mapx;i++)
  1210.     for(j=0;j<m->mapy;j++) {
  1211.       object *previous_obj=NULL;
  1212.         while((op=get_map_ob(m,i,j))!=NULL) {
  1213.           if (op==previous_obj)
  1214.           {
  1215.             LOG(llevDebug, "free_all_objects: Link error, bailing out.\n");
  1216.             break;
  1217.           }
  1218.           previous_obj=op;
  1219.           if(op->head!=NULL)
  1220.           op = op->head;
  1221.  
  1222.       /* If the map isn't in memory, free_object will remove and
  1223.        * free objects in op's inventory.  So let it do the job.
  1224.        */
  1225.       if (m->in_memory==MAP_IN_MEMORY)
  1226.         clean_object(op);
  1227.           remove_ob(op);
  1228.           free_object(op);
  1229.         }
  1230.       }
  1231. }
  1232.  
  1233. /*
  1234.  * This function moves all objects from one map to another.
  1235.  *
  1236.  * move_all_objects(): Only used from the editor(s?)
  1237.  * Yes. -Frank
  1238.  */
  1239.  
  1240. void move_all_objects(mapstruct *m1, mapstruct *m2) {
  1241.   int i,j;
  1242.   object *op;
  1243.  
  1244.   for(i=0;i<m1->mapx&&i<m2->mapx;i++)
  1245.     for(j=0;j<m1->mapy&&j<m2->mapy;j++) {
  1246.       while((op=get_map_ob(m1,i,j))!=NULL&&op->head==NULL) {
  1247.         remove_ob(op);
  1248.         op->x=i,op->y=j; /* Not really needed */
  1249.         insert_ob_in_map(op,m2);
  1250.       }
  1251.     }
  1252.   free_all_objects(m1);
  1253. }
  1254.  
  1255. /*
  1256.  * function: vanish mapstruct
  1257.  * m       : pointer to mapstruct, if NULL no action
  1258.  */
  1259.  
  1260. void delete_map(mapstruct *m) {
  1261.     mapstruct *tmp;
  1262.  
  1263.     if (!m)
  1264.       return;
  1265.     if (m->in_memory == MAP_IN_MEMORY)
  1266.     free_map (m, 1);
  1267.     if (m == first_map)
  1268.     first_map = m->next;
  1269.     else {
  1270.     for (tmp = first_map; tmp && tmp->next != m; tmp = tmp->next);
  1271.         if(tmp)
  1272.       tmp->next = m->next;
  1273.     }
  1274.     free (m);
  1275. }
  1276.  
  1277. /*
  1278.  * Frees everything allocated by the given mapstructure.
  1279.  */
  1280.  
  1281. void free_map(mapstruct *m,int flag) {
  1282.   if (!m->in_memory) {
  1283.     LOG(llevError,"Trying to free freed map.\n");
  1284.     return;
  1285.   }
  1286.   if(flag)
  1287.     free_all_objects(m);
  1288.   m->in_memory=MAP_SWAPPED;
  1289.   if (m->map != NULL)
  1290.     CFREE(m->map);
  1291.   if (m->map_ob != NULL)
  1292.     CFREE(m->map_ob);
  1293.   if (m->floor !=NULL)
  1294.     CFREE(m->floor);
  1295. #ifdef DOUBLE_FLOOR
  1296.   if (m->floor2 !=NULL)
  1297.     CFREE(m->floor2);
  1298. #endif
  1299.   m->map = NULL;/* It's being accessed again, incorrectly.  Maybe this will */
  1300.         /* make it get loaded back in. */
  1301.   m->map_ob = NULL;
  1302.   m->floor = NULL;
  1303. #ifdef DOUBLE_FLOOR
  1304.   m->floor2 = NULL;
  1305. #endif
  1306.   if (m->map_object)
  1307.       free_object (m->map_object);
  1308.   m->map_object=NULL;
  1309.   if (m->buttons)
  1310.     free_objectlinkpt(m->buttons);
  1311.   m->buttons = NULL;
  1312. }
  1313.  
  1314. /*
  1315.  * Allocates, initialises, and returns a pointer to a mapstruct.
  1316.  */
  1317.  
  1318. mapstruct *get_linked_map(char *path) {
  1319.   mapstruct *map=(mapstruct *) CALLOC(1,sizeof(mapstruct));
  1320.   mapstruct *mp;
  1321.  
  1322.   if(map==NULL)
  1323.     fatal(OUT_OF_MEMORY);
  1324.   for(mp=first_map;mp!=NULL&&mp->next!=NULL;mp=mp->next);
  1325.   if(mp==NULL)
  1326.     first_map=map;
  1327.   else
  1328.     mp->next=map;
  1329.   map->next=NULL;
  1330.   map->path[0]='\0';
  1331.   map->tmpname=NULL;
  1332.   map->encounter = 0;
  1333.   map->players=0;
  1334.   map->in_memory=MAP_SWAPPED;
  1335. /*  map->read_only=0;*/
  1336.   map->timeout=0;
  1337.   map->light = (objectlink *) NULL;
  1338.   map->darkness = 0;
  1339.   map->do_los=0;
  1340.   map->pending = (objectlink *) NULL;
  1341.   map->map_object = NULL;
  1342.   map->buttons = NULL;
  1343. #if defined(UNIQUE_ITEMS) && defined(LOCK_ITEMS)
  1344.   map->lock_items = 0;
  1345. #endif
  1346.   map->compressed = 0;
  1347.  
  1348.   return map;
  1349. }
  1350.  
  1351. /*
  1352.  * Allocates the arrays contained in a mapstruct.
  1353.  */
  1354.  
  1355. void allocate_map(mapstruct *m) {
  1356.   if(m->in_memory != MAP_SWAPPED )
  1357.     return;
  1358.   m->in_memory = MAP_IN_MEMORY;
  1359.   m->map=(MapLook *) CALLOC(m->mapx*m->mapy,sizeof(MapLook));
  1360.   m->floor=(MapLook *) CALLOC(m->mapx*m->mapy,sizeof(MapLook));
  1361.   m->map_ob=(object **) CALLOC(m->mapx*m->mapy,sizeof(object *));
  1362. #ifdef DOUBLE_FLOOR
  1363.   m->floor2=(MapLook *) CALLOC(m->mapx*m->mapy,sizeof(MapLook));
  1364.   if(m->map==NULL||m->map_ob==NULL || m->floor==NULL || m->floor2==NULL)
  1365.     fatal(OUT_OF_MEMORY);
  1366. #else
  1367.   if(m->map==NULL||m->map_ob==NULL || m->floor==NULL)
  1368.     fatal(OUT_OF_MEMORY);
  1369. #endif
  1370. }
  1371.  
  1372. /*
  1373.  * Creates an empty map of the given size, and returns a pointer to it.
  1374.  */
  1375.  
  1376. mapstruct *get_empty_map (int sizex, int sizey) {
  1377.     mapstruct *m = get_linked_map (NULL);
  1378.     archetype *tmp;
  1379.  
  1380.     for (tmp = first_archetype; tmp; tmp = tmp->next)
  1381.     if (tmp->clone.type == MAP)
  1382.         break;
  1383.     if (tmp) {
  1384.     m->map_object = ObjectCreateArch (tmp);
  1385.     m->mapx = sizex;
  1386.     m->mapy = sizey;
  1387.     allocate_map (m);
  1388.     clear_map (m);
  1389.     } else {
  1390.     m->map_object = NULL;
  1391.     LOG (llevError, "no map archetypes\n");
  1392.     }
  1393.     return m;
  1394. }
  1395.  
  1396. /*
  1397.  * Makes sure the given map is loaded and swapped in.
  1398.  * Returns a pointer to the given map.
  1399.  */
  1400.  
  1401. mapstruct *ready_map_name(char *name, int flush) {
  1402.     mapstruct *m;
  1403.  
  1404.     if (!name)
  1405.        return (NULL);
  1406.  
  1407.     /* Have we been at this level before? */
  1408.     m = has_been_loaded (name);
  1409.  
  1410.     if (m && (m->in_memory == MAP_LOADING || m->in_memory == MAP_IN_MEMORY))
  1411.       return m;
  1412.  
  1413.     if (flush || !m || (m->reset_time != -1 && seconds() > m->reset_time)) {
  1414.  
  1415.     /* first visit or time to reset */
  1416.     if (m) {
  1417.         clean_tmp_map(m);    /* Doesn't make much difference */
  1418.         delete_map(m);
  1419.     }
  1420.  
  1421.     /* create and load a map */
  1422.         LOG(llevDebug, "Trying to load map %s.\n", create_pathname(name));
  1423.       if (!(m = load_original_map(name, 0)))
  1424.         return (NULL);
  1425.  
  1426.     (*fix_auto_apply_func)(m); /* Chests which open as default */
  1427.  
  1428. #ifdef UNIQUE_ITEMS 
  1429.       if (!flush) /* load these only in the game */
  1430.           load_unique_objects(m);
  1431. #endif
  1432.     } else {
  1433.  
  1434.     load_temporary_map (m);
  1435. #ifdef UNIQUE_ITEMS 
  1436.       load_unique_objects(m);
  1437. #endif
  1438.  
  1439.     clean_tmp_map(m);
  1440.     m->in_memory = MAP_IN_MEMORY;
  1441.     /* tempnam() on sun systems (probably others) uses malloc
  1442.      * to allocated space for the string.  Free it here.
  1443.      */
  1444.     free(m->tmpname);
  1445.     m->tmpname = NULL;
  1446.     /* It's going to be saved anew anyway */
  1447.     }
  1448.  
  1449.     /* In case other objects press some buttons down */
  1450.     (*update_buttons_func)(m);
  1451.  
  1452.     return m;
  1453. }
  1454.  
  1455.  
  1456.  
  1457. void no_maps_file(char *filename) {
  1458.   LOG(llevError,"Can't open the %s file.\n",filename);
  1459.   LOG(llevError,"If you have no maps, you must either make them yourself\n");
  1460.   LOG(llevError,"with the mapeditor, or fetch them from ftp.ifi.uio.no\n");
  1461.   LOG(llevError,"in the /pub/crossfire directory.  Be sure not to fetch\n");
  1462.   LOG(llevError,"maps belonging to a later version than this version.\n");
  1463.   exit(-1);
  1464. }
  1465.  
  1466.  
  1467. void set_map_reset_time(mapstruct *map) {
  1468. #ifdef MAP_RESET
  1469. #ifdef MAP_MAXRESET
  1470.     if (MAP_RESETTIME(map)>MAP_MAXRESET)
  1471.     map->reset_time = seconds() + MAP_MAXRESET;
  1472.     else
  1473. #endif /* MAP_MAXRESET */
  1474.     map->reset_time = seconds() + MAP_RESETTIME (map);
  1475. #else
  1476.     map->reset_time = (-1); /* Will never be reset */
  1477. #endif
  1478. }
  1479.  
  1480. /*
  1481.  * This routine is supposed to find out which level the players should have
  1482.  * before visiting this map.  It is used to calculate which bonuses to put
  1483.  * on magic items.
  1484.  *
  1485.  * Difficulty can now be set by the map creature.  If the value stored
  1486.  * in the map is zero, then use this routine.
  1487.  */
  1488.  
  1489. int calculate_difficulty(mapstruct *m) {
  1490.   object *op;
  1491.   archetype *at;
  1492.   int x,y;
  1493.   int diff=0;
  1494.   int total_exp=0,exp_pr_sq;
  1495.   int i;
  1496.  
  1497.   if (MAP_DIFFICULTY(m)) {
  1498.     LOG(llevDebug, "Using stored map difficulty: %d\n", MAP_DIFFICULTY(m));
  1499.     return MAP_DIFFICULTY(m);
  1500.   }
  1501.   for(x=0;x<m->mapx;x++)
  1502.     for(y=0;y<m->mapy;y++)
  1503.       for(op=get_map_ob(m,x,y);op!=NULL;op=op->above) {
  1504.         if(QUERY_FLAG(op,FLAG_MONSTER))
  1505.           total_exp+=op->stats.exp;
  1506.         if(QUERY_FLAG(op,FLAG_GENERATOR)) {
  1507.           total_exp+=op->stats.exp;
  1508.           at=type_to_archetype(GENERATE_TYPE(op));
  1509.           if(at!=NULL)
  1510.             total_exp+=at->clone.stats.exp*8;
  1511.         }
  1512.       }
  1513. #ifdef NEWCALC
  1514.   (int)exp_pr_sq=((double)1000*total_exp)/(m->mapx*m->mapy+1);
  1515.   for(i=20;i>0;i--)
  1516.     if(exp_pr_sq>level_exp(i,1.0)) {
  1517.       diff=i;
  1518.       break;
  1519.     }
  1520. #else
  1521.   exp_pr_sq=((double)1000*total_exp)/(m->mapx*m->mapy+1);
  1522.   diff=20;
  1523.   for(i=1;i<20;i++)
  1524.     if(exp_pr_sq<=level_exp(i,1.0)) {
  1525.       diff=i;
  1526.       break;
  1527.     }
  1528. #endif
  1529.   return diff;
  1530. }
  1531.  
  1532. void clean_tmp_map(mapstruct *m) {
  1533.   if(m->tmpname == NULL)
  1534.     return;
  1535.   (void) unlink(m->tmpname);
  1536. }
  1537.  
  1538. /*
  1539.  * member: copy by translate objects from source to a new map
  1540.  * source: -map
  1541.  * width : width of target map
  1542.  * height: height of target map
  1543.  * dx    : positive translate to right
  1544.  * dy    : positive translate to down
  1545.  */
  1546. mapstruct *MapMoveScrollResize(mapstruct *source, 
  1547.                 int width, int height, int dx, int dy) 
  1548. {
  1549.     mapstruct *target;
  1550.     object *obj,*prt; /* PaRT of obj */
  1551.     int x,y,sx = source->mapx, sy = source->mapy;
  1552.     int linked = 0, link=0;
  1553.  
  1554.     if (!width) width = sx;
  1555.     if (!height) height = sy;
  1556.     target = get_empty_map (width, height);
  1557.  
  1558.     strncpy (target->path, source->path, BIG_NAME);
  1559.  
  1560.     copy_object (source->map_object, target->map_object);
  1561.     target->mapx = width;
  1562.     target->mapy = height;  
  1563.  
  1564.     if(dx < 0) dx += target->mapx;
  1565.     if(dy < 0) dy += target->mapy;
  1566.  
  1567.     for(y=0; y < sy && y < target->mapy; y++)
  1568.     for(x=0; x < sx && x < target->mapx; x++)
  1569.         while((obj = get_map_ob(source,x,y)) && !obj->head) {
  1570.         if ((linked = QUERY_FLAG (obj,FLAG_IS_LINKED))) {
  1571.             link = get_button_value (obj);
  1572.             remove_button_link (obj);
  1573.         }
  1574.         remove_ob(obj);
  1575.         for(prt = obj; prt; prt = prt->more) {
  1576.             prt->x += dx;
  1577.             prt->x %= target->mapx; /* it can be split by edge */
  1578.             prt->y += dy;           /* designers problem to fix */
  1579.             prt->y %= target->mapy;
  1580.         }
  1581.         insert_ob_in_map(obj,target);
  1582.         if (linked)
  1583.             add_button_link(obj, target, link);
  1584.         }
  1585.     /*free_all_objects(source);*/
  1586.     free_map (source, 1);
  1587.     delete_map (source);
  1588.     return target;
  1589. }
  1590.  
  1591. /*
  1592.  * member: copy by translate objects from source to target
  1593.  * target: -map
  1594.  * source: -map
  1595.  * dx    : positive translate to right
  1596.  * dy    : positive translate to down
  1597.  */
  1598. void MapMoveScroll(mapstruct *target, mapstruct *source, int dx, int dy) 
  1599. {
  1600.     object *obj,*prt; /* PaRT of obj */
  1601.     int x,y;
  1602.  
  1603.     if(dx < 0) dx += target->mapx;
  1604.     if(dy < 0) dy += target->mapy;
  1605.  
  1606.     for(y=0; y < source->mapy && y < target->mapy; y++)
  1607.     for(x=0; x < source->mapx && x < target->mapx; x++)
  1608.         while((obj = get_map_ob(source,x,y)) && !obj->head) {
  1609.         remove_ob(obj);
  1610.         for(prt = obj; prt; prt = prt->more) {
  1611.             prt->x += dx;
  1612.             prt->x %= target->mapx; /* it can be split by edge */
  1613.             prt->y += dy;           /* designers problem to fix */
  1614.             prt->y %= target->mapy;
  1615.         }
  1616.         insert_ob_in_map(obj,target);
  1617.         }
  1618.     free_all_objects(source);
  1619. }
  1620.  
  1621. object * MapGetRealObject (mapstruct * emap, int x, int y, int z)
  1622. {
  1623.     object *tmp = MapGetObjectZ (emap, x, y, z);
  1624.     return tmp ? (tmp->head ? tmp->head : tmp) : tmp;
  1625. }
  1626.  
  1627. int MapInsertObjectZ(mapstruct *emap,object *o,int x, int y, int z)
  1628. {
  1629.     object *op, *above, *below;
  1630.  
  1631.     if (o->more)
  1632.         MapInsertObjectZ (emap,o->more, x, y, z);
  1633.  
  1634.     o->x += x;
  1635.     o->y += y;
  1636.     o->map = emap;
  1637.     CLEAR_FLAG(o,FLAG_REMOVED);
  1638.  
  1639.     op = get_map_ob (emap, o->x, o->y);
  1640.     if (z < 0) {
  1641.     above = op;
  1642.     below = NULL;
  1643.     } else {
  1644.     while (op && op->above)
  1645.         op = op->above;
  1646.     
  1647.     above = NULL;
  1648.     below = op;
  1649.     while (op && z-- > 0) {
  1650.         above = op;
  1651.         below = op = op->below;
  1652.     }
  1653.     }
  1654.     o->below = below;
  1655.     o->above = above;
  1656.  
  1657.     if (above)
  1658.         above->below = o;
  1659.     else {
  1660.     MapLook f;
  1661.     f.flags = 0;
  1662.     f.face = o->face;
  1663.     set_map (emap, o->x, o->y, &f);
  1664.     }
  1665.     if (below)
  1666.         below->above = o;
  1667.     else
  1668.         set_map_ob (emap, o->x, o->y, o);
  1669.     
  1670.     return (0);
  1671. }
  1672.  
  1673. int MapObjectOut (mapstruct *target, object *obj, int x, int y) {
  1674.     object *tmp;
  1675.     for(tmp = obj; tmp; tmp = tmp->more)
  1676.         if(out_of_map(target,x + tmp->x,y + tmp->y)) return 1;
  1677.     return 0;
  1678. }
  1679.  
  1680. object * MapGetObjectZ (mapstruct * emap, int x, int y, int z)
  1681. {
  1682.     object *op;
  1683.  
  1684.     if (!emap || out_of_map (emap, x, y))
  1685.         return (NULL);
  1686.     op = get_map_ob (emap, x, y);
  1687.     while (op && op->above)
  1688.         op = op->above;
  1689.     while (op && z-- > 0)
  1690.         op = op->below;
  1691.     return (op);
  1692. }
  1693.  
  1694. /* baptize_altar() - (cosmetically) change the name to that of the
  1695.  * god in question, then set the title for later use. -b.t.
  1696.  */
  1697.  
  1698. int baptize_altar(object *op) {
  1699.    char buf[MAX_BUF];
  1700.    int i = RANDOM()%NROFGODS;
  1701.  
  1702.    /* if the object name hasnt' been changed, we give it a random god */
  1703.    if(!strcmp(op->name,op->arch->clone.name)) {
  1704.         if(op->name!=NULL) free_string(op->name);
  1705.         sprintf(buf,"%s of %s",op->name,Gods[i].name);
  1706.         op->name = add_string(buf);
  1707.    }
  1708.    if(!op->title) {
  1709.         op->title=add_string(Gods[i].name);
  1710.         return 1;
  1711.    }
  1712.    return 0;
  1713. }
  1714.  
  1715.